package order

import (
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"shopstar/global"
	"shopstar/models"
	"shopstar/models/goods"
	"shopstar/models/order"
	"strconv"
	"strings"
)

type Cart struct{}

var CartService = new(Cart)

func (*Cart) Add(skuId int64, userId string, shopId, num int) error {
	var goodsSku goods.GoodsSku
	models.DB.Where("id = ?", skuId).First(&goodsSku)

	if goodsSku.Stock-num < 0 {
		return global.ErrCartSkuNumDeficiency
	}

	var cart order.Cart
	db := models.DB.Where("sku_id = ? and user_id = ? ", skuId, userId).First(&cart)
	if db.RowsAffected > 0 {
		db.Update("goods_num", cart.GoodsNum+num)
		return nil
	}

	cart.SkuId = skuId
	cart.UserId = userId
	cart.ShopId = shopId
	cart.GoodsNum = num
	cart.GoodsName = goodsSku.Title
	cart.GoodsPrice = goodsSku.Price

	models.DB.Create(&cart)

	return nil
}

func (*Cart) GetCartByUserId(userId string) []order.Cart {
	var ret []order.Cart
	models.DB.Where("user_id = ?", userId).Find(&ret)
	return ret
}

func (c *Cart) GetCartById(cartIds ...int) []*order.Cart {
	var tmp []*order.Cart
	models.DB.Where("id", cartIds).Group("shop_id, id").Find(&tmp)
	return tmp
}

func (c *Cart) CreateOrder(userId string, cartId string) (err error) {
	strCartIds := strings.Split(cartId, ",")
	cartIds := make([]int, len(strCartIds))
	for k, v := range strCartIds {
		cartIds[k], _ = strconv.Atoi(v)
	}
	carts := make(map[int][]*order.Cart, 0)
	for _, v := range c.GetCartById(cartIds...) {
		carts[v.ShopId] = append(carts[v.ShopId], v)
	}
	err = models.DB.Transaction(func(tx *gorm.DB) error {
		for sid, v := range carts {
			sum := decimal.NewFromInt(0)
			var orderGoods []*order.OrderGoods
			for _, cart := range v {
				tmp := cart.GoodsPrice.Mul(decimal.NewFromInt(int64(cart.GoodsNum)))
				orderGoods = append(orderGoods, &order.OrderGoods{
					SkuId:       cart.SkuId,
					ShopId:      sid,
					GoodsName:   cart.GoodsName,
					GoodsNum:    cart.GoodsNum,
					GoodsPrice:  cart.GoodsPrice,
					TotalAmount: tmp,
				})
				sum = sum.Add(tmp)
			}
			// 订单的生成
			err := OrderService.CreateOrder(userId, sid, sum, orderGoods)
			if err != nil {
				return err
			}
		}
		return nil
	})
	return
}
